package com.lifeverse.controller;

import com.lifeverse.common.ApiResponse;
import com.lifeverse.entity.AuditLog;
import com.lifeverse.entity.enums.AuditAction;
import com.lifeverse.entity.enums.AuditResult;
import com.lifeverse.service.AuditLogService;
import com.lifeverse.service.ComplianceReportService;
import com.lifeverse.service.SystemBehaviorTracker;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 审计日志控制器
 * 提供审计日志查询、分析和报告功能的REST API
 */
@RestController
@RequestMapping("/api/audit")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "审计日志管理", description = "审计日志查询、分析和报告API")
public class AuditLogController {
    
    private final AuditLogService auditLogService;
    private final SystemBehaviorTracker systemBehaviorTracker;
    private final ComplianceReportService complianceReportService;
    
    /**
     * 分页查询审计日志
     */
    @GetMapping("/logs")
    @Operation(summary = "分页查询审计日志", description = "根据条件分页查询审计日志")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<Page<AuditLog>>> getAuditLogs(
            @Parameter(description = "用户ID") @RequestParam(required = false) String userId,
            @Parameter(description = "操作类型") @RequestParam(required = false) AuditAction action,
            @Parameter(description = "操作结果") @RequestParam(required = false) AuditResult result,
            @Parameter(description = "资源类型") @RequestParam(required = false) String resourceType,
            @Parameter(description = "开始时间") @RequestParam(required = false) 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam(required = false) 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime,
            @Parameter(description = "最小风险等级") @RequestParam(required = false) Integer minRiskLevel,
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "20") int size,
            @Parameter(description = "排序字段") @RequestParam(defaultValue = "timestamp") String sortBy,
            @Parameter(description = "排序方向") @RequestParam(defaultValue = "desc") String sortDir) {
        
        try {
            Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
            Pageable pageable = PageRequest.of(page, size, sort);
            
            Page<AuditLog> auditLogs = auditLogService.findByMultipleConditions(
                    userId, action, result, resourceType, startTime, endTime, minRiskLevel, pageable);
            
            return ResponseEntity.ok(ApiResponse.success(auditLogs));
        } catch (Exception e) {
            log.error("查询审计日志失败", e);
            return ResponseEntity.ok(ApiResponse.error("查询审计日志失败: " + e.getMessage()));
        }
    }
    
    /**
     * 根据用户ID查询审计日志
     */
    @GetMapping("/logs/user/{userId}")
    @Operation(summary = "查询用户审计日志", description = "查询指定用户的审计日志")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR') or #userId == authentication.name")
    public ResponseEntity<ApiResponse<Page<AuditLog>>> getUserAuditLogs(
            @Parameter(description = "用户ID") @PathVariable String userId,
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "20") int size) {
        
        try {
            Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "timestamp"));
            Page<AuditLog> auditLogs = auditLogService.findByUserId(userId, pageable);
            
            return ResponseEntity.ok(ApiResponse.success(auditLogs));
        } catch (Exception e) {
            log.error("查询用户审计日志失败: userId={}", userId, e);
            return ResponseEntity.ok(ApiResponse.error("查询用户审计日志失败: " + e.getMessage()));
        }
    }
    
    /**
     * 查询用户登录历史
     */
    @GetMapping("/logs/user/{userId}/login-history")
    @Operation(summary = "查询用户登录历史", description = "查询指定用户的登录历史记录")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR') or #userId == authentication.name")
    public ResponseEntity<ApiResponse<Page<AuditLog>>> getUserLoginHistory(
            @Parameter(description = "用户ID") @PathVariable String userId,
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "20") int size) {
        
        try {
            Pageable pageable = PageRequest.of(page, size);
            Page<AuditLog> loginHistory = auditLogService.getUserLoginHistory(userId, pageable);
            
            return ResponseEntity.ok(ApiResponse.success(loginHistory));
        } catch (Exception e) {
            log.error("查询用户登录历史失败: userId={}", userId, e);
            return ResponseEntity.ok(ApiResponse.error("查询用户登录历史失败: " + e.getMessage()));
        }
    }
    
    /**
     * 查询失败的操作
     */
    @GetMapping("/logs/failures")
    @Operation(summary = "查询失败操作", description = "查询系统中失败的操作记录")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<Page<AuditLog>>> getFailedOperations(
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "20") int size) {
        
        try {
            Pageable pageable = PageRequest.of(page, size);
            Page<AuditLog> failedOperations = auditLogService.findFailedOperations(pageable);
            
            return ResponseEntity.ok(ApiResponse.success(failedOperations));
        } catch (Exception e) {
            log.error("查询失败操作失败", e);
            return ResponseEntity.ok(ApiResponse.error("查询失败操作失败: " + e.getMessage()));
        }
    }
    
    /**
     * 查询敏感操作
     */
    @GetMapping("/logs/sensitive")
    @Operation(summary = "查询敏感操作", description = "查询系统中的敏感操作记录")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<Page<AuditLog>>> getSensitiveOperations(
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "20") int size) {
        
        try {
            Pageable pageable = PageRequest.of(page, size);
            Page<AuditLog> sensitiveOperations = auditLogService.findSensitiveOperations(pageable);
            
            return ResponseEntity.ok(ApiResponse.success(sensitiveOperations));
        } catch (Exception e) {
            log.error("查询敏感操作失败", e);
            return ResponseEntity.ok(ApiResponse.error("查询敏感操作失败: " + e.getMessage()));
        }
    }
    
    /**
     * 查询高风险操作
     */
    @GetMapping("/logs/high-risk")
    @Operation(summary = "查询高风险操作", description = "查询系统中的高风险操作记录")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<Page<AuditLog>>> getHighRiskOperations(
            @Parameter(description = "最小风险等级") @RequestParam(defaultValue = "4") Integer minRiskLevel,
            @Parameter(description = "页码") @RequestParam(defaultValue = "0") int page,
            @Parameter(description = "页大小") @RequestParam(defaultValue = "20") int size) {
        
        try {
            Pageable pageable = PageRequest.of(page, size);
            Page<AuditLog> highRiskOperations = auditLogService.findHighRiskOperations(minRiskLevel, pageable);
            
            return ResponseEntity.ok(ApiResponse.success(highRiskOperations));
        } catch (Exception e) {
            log.error("查询高风险操作失败", e);
            return ResponseEntity.ok(ApiResponse.error("查询高风险操作失败: " + e.getMessage()));
        }
    }
    
    /**
     * 获取操作统计
     */
    @GetMapping("/statistics/actions")
    @Operation(summary = "获取操作统计", description = "获取指定时间范围内的操作类型统计")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<List<Object[]>>> getActionStatistics(
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        
        try {
            List<Object[]> statistics = auditLogService.getActionStatistics(startTime, endTime);
            return ResponseEntity.ok(ApiResponse.success(statistics));
        } catch (Exception e) {
            log.error("获取操作统计失败", e);
            return ResponseEntity.ok(ApiResponse.error("获取操作统计失败: " + e.getMessage()));
        }
    }
    
    /**
     * 获取结果统计
     */
    @GetMapping("/statistics/results")
    @Operation(summary = "获取结果统计", description = "获取指定时间范围内的操作结果统计")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<List<Object[]>>> getResultStatistics(
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        
        try {
            List<Object[]> statistics = auditLogService.getResultStatistics(startTime, endTime);
            return ResponseEntity.ok(ApiResponse.success(statistics));
        } catch (Exception e) {
            log.error("获取结果统计失败", e);
            return ResponseEntity.ok(ApiResponse.error("获取结果统计失败: " + e.getMessage()));
        }
    }
    
    /**
     * 查找可疑IP地址
     */
    @GetMapping("/security/suspicious-ips")
    @Operation(summary = "查找可疑IP", description = "查找指定时间范围内的可疑IP地址")
    @PreAuthorize("hasRole('ADMIN') or hasRole('SECURITY_ANALYST')")
    public ResponseEntity<ApiResponse<List<Object[]>>> getSuspiciousIpAddresses(
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime,
            @Parameter(description = "操作次数阈值") @RequestParam(defaultValue = "100") Long threshold) {
        
        try {
            List<Object[]> suspiciousIps = auditLogService.findSuspiciousIpAddresses(startTime, endTime, threshold);
            return ResponseEntity.ok(ApiResponse.success(suspiciousIps));
        } catch (Exception e) {
            log.error("查找可疑IP失败", e);
            return ResponseEntity.ok(ApiResponse.error("查找可疑IP失败: " + e.getMessage()));
        }
    }
    
    /**
     * 分析用户行为模式
     */
    @GetMapping("/behavior/user/{userId}")
    @Operation(summary = "分析用户行为", description = "分析指定用户的行为模式")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<List<SystemBehaviorTracker.BehaviorPattern>>> analyzeUserBehavior(
            @Parameter(description = "用户ID") @PathVariable String userId,
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        
        try {
            List<SystemBehaviorTracker.BehaviorPattern> patterns = 
                    systemBehaviorTracker.analyzeUserBehaviorPatterns(userId, startTime, endTime);
            return ResponseEntity.ok(ApiResponse.success(patterns));
        } catch (Exception e) {
            log.error("分析用户行为失败: userId={}", userId, e);
            return ResponseEntity.ok(ApiResponse.error("分析用户行为失败: " + e.getMessage()));
        }
    }
    
    /**
     * 检测异常行为
     */
    @GetMapping("/behavior/anomalies")
    @Operation(summary = "检测异常行为", description = "检测指定时间范围内的异常行为")
    @PreAuthorize("hasRole('ADMIN') or hasRole('SECURITY_ANALYST')")
    public ResponseEntity<ApiResponse<List<SystemBehaviorTracker.AnomalyDetectionResult>>> detectAnomalies(
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        
        try {
            List<SystemBehaviorTracker.AnomalyDetectionResult> anomalies = 
                    systemBehaviorTracker.detectAnomalies(startTime, endTime);
            return ResponseEntity.ok(ApiResponse.success(anomalies));
        } catch (Exception e) {
            log.error("检测异常行为失败", e);
            return ResponseEntity.ok(ApiResponse.error("检测异常行为失败: " + e.getMessage()));
        }
    }
    
    /**
     * 生成行为分析报告
     */
    @GetMapping("/behavior/report")
    @Operation(summary = "生成行为报告", description = "生成指定时间范围内的行为分析报告")
    @PreAuthorize("hasRole('ADMIN') or hasRole('AUDITOR')")
    public ResponseEntity<ApiResponse<Map<String, Object>>> generateBehaviorReport(
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        
        try {
            Map<String, Object> report = systemBehaviorTracker.generateBehaviorReport(startTime, endTime);
            return ResponseEntity.ok(ApiResponse.success(report));
        } catch (Exception e) {
            log.error("生成行为分析报告失败", e);
            return ResponseEntity.ok(ApiResponse.error("生成行为分析报告失败: " + e.getMessage()));
        }
    }
    
    /**
     * 生成合规性报告
     */
    @GetMapping("/compliance/report")
    @Operation(summary = "生成合规性报告", description = "生成指定类型的合规性报告")
    @PreAuthorize("hasRole('ADMIN') or hasRole('COMPLIANCE_OFFICER')")
    public ResponseEntity<ApiResponse<ComplianceReportService.ComplianceReport>> generateComplianceReport(
            @Parameter(description = "报告类型") @RequestParam ComplianceReportService.ComplianceReportType reportType,
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        
        try {
            ComplianceReportService.ComplianceReport report = 
                    complianceReportService.generateComplianceReport(reportType, startTime, endTime);
            return ResponseEntity.ok(ApiResponse.success(report));
        } catch (Exception e) {
            log.error("生成合规性报告失败: reportType={}", reportType, e);
            return ResponseEntity.ok(ApiResponse.error("生成合规性报告失败: " + e.getMessage()));
        }
    }
    
    /**
     * 导出合规性报告为文本
     */
    @GetMapping("/compliance/report/export")
    @Operation(summary = "导出合规性报告", description = "导出合规性报告为文本格式")
    @PreAuthorize("hasRole('ADMIN') or hasRole('COMPLIANCE_OFFICER')")
    public ResponseEntity<String> exportComplianceReport(
            @Parameter(description = "报告类型") @RequestParam ComplianceReportService.ComplianceReportType reportType,
            @Parameter(description = "开始时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @Parameter(description = "结束时间") @RequestParam 
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        
        try {
            ComplianceReportService.ComplianceReport report = 
                    complianceReportService.generateComplianceReport(reportType, startTime, endTime);
            String textReport = complianceReportService.exportReportAsText(report);
            
            return ResponseEntity.ok()
                    .header("Content-Type", "text/plain; charset=utf-8")
                    .header("Content-Disposition", "attachment; filename=\"compliance_report_" + 
                            reportType.name().toLowerCase() + "_" + 
                            startTime.toLocalDate() + "_to_" + endTime.toLocalDate() + ".txt\"")
                    .body(textReport);
        } catch (Exception e) {
            log.error("导出合规性报告失败: reportType={}", reportType, e);
            return ResponseEntity.internalServerError()
                    .body("导出合规性报告失败: " + e.getMessage());
        }
    }
}